#include "stm32f10x.h"
#include "AtCmd.h"

#include "sys.h"
#include "OLED.h"
#include "Serial.h"
#include "StringFun.h"

// AT指令缓冲区
char at_cmd_buffer[AT_CMD_BUFFER_SIZE];

//static char at_cmd_param[PARAM_BUFFER_SIZE]; // 指令参数

//static char at_cmd_response[RESPONSE_BUFFER_SIZE]; // 指令响应

AtCmd_t at_cmd; // 指令结构体
uint8_t at_cmd_config_flag;     // 指令配置标志位

uint8_t at_cmd_start_flag; // 指令开始标志位

AT_Command_State at_cmd_state = AT_IDLE;   // 当前状态
Response_State response_state = RESPONSE_IDLE; // 响应状态

Data_State data_state = DATA_IDLE; // FTP数据状态


// FTP数据接收缓冲区
char ftp_data_buffer[1024] ;


// 数据处理状态机
void Data_Process(void);
// 请求处理状态机
void AT_Response_Process(void);


// 构造AT指令
char* Build_At_Command(void)
{
    if(at_cmd_config_flag == 0) {
        return NULL;
    }

    const char* cmd = at_cmd.cmd;
    const char* param = at_cmd.param;

    /* 格式化缓冲区 */
    memset(at_cmd_buffer, 0, sizeof(at_cmd_buffer)); // 格式化指令缓冲区

    // 构造AT指令
    if((cmd[0] != 'A' && cmd[1] != 'T')) {
        strcat(at_cmd_buffer, "AT+");
    }

    strcat(at_cmd_buffer, cmd); // 追加指令名称
    if(param != NULL) {
        strcat(at_cmd_buffer, "="); // 追加参数分隔符
        strcat(at_cmd_buffer, param); // 追加参数
    } 
	strcat(at_cmd_buffer, "\r\n"); // 追加回车换行符
    
    return at_cmd_buffer;
}

// 处理AT响应数据
void At_Command_Config_Clear(void)
{
    memset(at_cmd.cmd, 0, sizeof(at_cmd.cmd)); // 格式化指令名称
    memset(at_cmd.param, 0, sizeof(at_cmd.param)); // 格式化参数
    memset(at_cmd.response, 0, sizeof(at_cmd.response)); // 格式化响应
    at_cmd.timeout = 0; // 格式化超时时间
    at_cmd.wait_time = 0; // 格式化等待时间

    at_cmd_config_flag = 0; // 指令配置标志位
}

// 初始化配置
void At_Command_Init(void)
{
    At_Command_Config_Clear(); // 格式化指令配置
    at_cmd.timeout = AT_CMD_TIMEOUT; // 格式化超时时间
}

// 配置AT指令
uint8_t At_Command_Config(const char *cmd, const char *param, const char *response, uint16_t wait, uint16_t timeout)
{
    // // 检查参数合法性
    // if(cmd == NULL || strlen(cmd) == 0 || strlen(cmd) > CMD_BUFFER_SIZE) {
    //     return 0;
    // }

    // if(param != NULL && strlen(param) > PARAM_BUFFER_SIZE) {
    //     return 0;
    // }

    // if(response != NULL && strlen(response) > RESPONSE_BUFFER_SIZE) {
    //     return 0;
    // }

    At_Command_Config_Clear(); // 格式化指令配置

    stringCopy(at_cmd.cmd, cmd); // 配置指令名称
    if(param != NULL) {
        stringCopy(at_cmd.param, param); // 配置参数
    }

    if(response != NULL) {
        stringCopy(at_cmd.response, response); // 配置响应
    }

    at_cmd.timeout = timeout; // 配置超时时间
    at_cmd.wait_time = wait; // 配置等待时间

    at_cmd_config_flag = 1; // 指令配置标志位

    return at_cmd_config_flag;
}

// 发送AT指令
void At_Command_Applictaion(const char* cmd, const char* param, const char* response, uint16_t wait, uint16_t timeout)
{
    // 配置指令
    At_Command_Config(cmd, param, response, wait, timeout);

    // 构造AT指令
    Build_At_Command();

    // 开启AT指令状态机
    at_cmd_start_flag = 1; // 指令开始标志位
}

// 判断是否接收完毕
uint8_t Check_Receive_Complete(void)
{
    return Serial_Is_Idle();    // 判断是否已经空闲
}


// 处理AT指令 状态机
void At_Command_Process(void)
{
    static uint8_t timeout_count = 0; // 超时计数器
//    static uint32_t timeout = 0;      // 超时计数器
    static uint32_t time_stamp = 0;   // 时间戳
    static uint32_t wait_xms = 0;     // 等待时间

    switch(at_cmd_state) {
        case AT_IDLE: // 空闲状态
            // 开始处理指令
            if(at_cmd_start_flag == 1) {

                Serial_Rx_Buffer_Clear(); // 清空接收缓冲区

                at_cmd_state = AT_START; // 进入发送状态
            }
            break;
        case AT_START: // 发送状态
            // 发送AT指令
            Serial_SendString(at_cmd_buffer);
            OLED_ShowNum(1, 4, strlen(at_cmd_buffer), 3);
            OLED_ShowString(2, 1, at_cmd.cmd);
            // wait_xms = 20; // 等待20ms 
            time_stamp = GetSystemTick(); // 记录时间戳
            at_cmd_state = AT_SENDING; // 进入等待响应状态
            break;
        case AT_SENDING: // 等待响应状态

            // 延时20ms 模拟发送耗时
            if((GetSystemTick() - time_stamp >= 20))
            {
                time_stamp = GetSystemTick(); // 记录时间戳
                at_cmd_state = AT_WAITING_RESPONSE; // 进入等待模块响应状态
            }
            
            break;
        case AT_WAITING_RESPONSE: // 等待模块响应状态

            // 超时判断
            if(GetSystemTick() - time_stamp < at_cmd.timeout) {
                timeout_count++; // 超时计数器加1
                response_state = RESPONSE_TIMEOUT; // 超时
                
                if(timeout_count >= 3) {
                    timeout_count = 0; // 超时计数器清零
                    response_state = RESPONSE_NULL; // 超时3次 无响应
                }

                at_cmd_state = AT_END; // 进入指令结束状态
            }

            // 判断串口接收缓冲区是否有数据
            if(Serial_Rx_Length == 0) {
                return;
            }
    
            // 判断是否接收完毕
            if(Check_Receive_Complete() == 0) {
                wait_xms = GetSystemTick(); // 记录时间戳
                return;
            }

            // 判断等待时间是否结束
            if(GetSystemTick() - wait_xms >= at_cmd.wait_time) {

                at_cmd_state = AT_DATA_PROCESSING; // 进入指令结束状态
            }
            break;

        case AT_DATA_PROCESSING: // 数据处理状态
            
            // 处理AT响应数据
            AT_Response_Process();

            // 判断是否接收完毕
            if(response_state == RESPONSE_END) {
                at_cmd_state = AT_END; // 进入指令结束状态
            }
            
            break;
        case AT_END: // 指令结束状态
            // 处理AT响应
            at_cmd_state = AT_IDLE; // 进入空闲状态
            at_cmd_start_flag = 0; // 指令开始标志位
            break;
        default:
            at_cmd_state = AT_IDLE; // 进入空闲状态
            break;
    }
}

void Check_Response_Data(const char *rx_buf, uint16_t len)
{
    if(stringFind(rx_buf, AT_CMD_RESPONSE_ERROR)) {
        response_state = RESPONSE_ERROR; // 错误响应
    } else if(stringFind(rx_buf, AT_CMD_RESPONSE_OK)){
        response_state = RESPONSE_SUCCESS; // 成功响应
    } else if(stringFind(rx_buf, AT_CMD_RESPONSE_DATA)) {
        response_state = RESPONSE_SUCCESS; // 成功响应
    }
    else {
        // 处理其他响应数据
        
        // 未定义类型
        OLED_ShowString(3, 6, "UnKnown"); // 显示未定义类型
        response_state = RESPONSE_END; // 响应结束
    }
}

// 处理AT响应
void AT_Response_Process(void)
{

    // 处理AT响应数据
    switch(response_state) {
        case RESPONSE_IDLE: // 空闲状态
            // 判断是否接收完毕

            // 检查响应数据类型
            Check_Response_Data(Serial_Rx_Buffer, Serial_Rx_Length);

            break;
        case RESPONSE_TIMEOUT: // 超时状态
            // 处理超时响应


            break;
        case RESPONSE_NULL: // 无响应状态
            // 处理无响应响应

            break;
        case RESPONSE_SUCCESS: // 成功状态
            // 处理成功响应

            Data_Process(); // 处理数据

            break;
        case RESPONSE_ERROR: // 错误状态
            // 处理错误响应

            break;
        case RESPONSE_END: // 响应结束状态
            // 处理响应结束

            break;
        default:
            response_state = RESPONSE_IDLE; // 空闲状态
            break;
    }
}

// 处理数据 状态机
void Data_Process(void)
{
	uint16_t dataLength;
	char* dataPtr;
    // 处理数据
    switch(data_state) {
        case DATA_IDLE: // 空闲状态
            // 处理数据
            break;
        case DATA_PROCESSING: // 数据处理状态
            // 处理数据

            // 提取数据
            dataLength = 0;
            dataPtr = strstr(Serial_Rx_Buffer, AT_CMD_RESPONSE_DATA);
            
            if(dataPtr != NULL)
            {
                // 解析数据长度
                dataPtr += strlen(AT_CMD_RESPONSE_DATA);
                while(*dataPtr >= '0' && *dataPtr <= '9')
                {
                    dataLength = dataLength * 10 + (*dataPtr - '0');
                    dataPtr++;
                }
                
                // 跳过"\r\n"
                dataPtr += 2;
                
                // 复制数据到缓冲区
                if(dataLength > 0 && dataLength < sizeof(ftp_data_buffer) - 3)
                {
                    memset(ftp_data_buffer, 0, sizeof(ftp_data_buffer));
                    memcpy(ftp_data_buffer, dataPtr, dataLength);
                    strcat(ftp_data_buffer, "\r\n");
                    
                    // 显示数据
                }
            }
            
            // 重置状态
            data_state = DATA_END; // 进入数据结束状态

            break;
        case DATA_END: // 数据结束状态
            // 处理数据结束
            if(strlen(ftp_data_buffer) > 0) {
                OLED_ShowString(0, 6, ftp_data_buffer); // 显示数据
            }
            data_state = DATA_IDLE; // 进入空闲状态
            break;
        default:
            data_state = DATA_IDLE; // 空闲状态
            break;
    }

}
